package pers.vic.practice;

import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;

/**
 * 描述:多线程实例:龟兔赛跑
 * <p>
 *     编写多线程 MyThread 类，完成编写一个模拟龟兔赛跑的程序。
 *     分别用一个线程代表乌龟和兔子，用线程休眠代表动物“打盹”，打盹
 *     前后输出说明打盹时间；不休眠的时候表示动物“前进”，每过一个时
 *     间单位输出当前位置。
 * </p>
 * @author Vic.xu
 * @date 2022-04-01 10:41
 */
public class MyThread extends Thread {

    /**
     * 赛道长度
     */
    private static final int DISTANCE = 100;

    /***
     * 比赛是否结束
     */
    private static volatile boolean finished = false;

    /**
     * name
     */
    private final String name;

    /**
     * 速度
     */
    private final int speed;

    /**
     * 打盹范围 s [2,10] 请限定在2 到5秒以内
     */
    private final int napRange;

    /**
     * 构造线程
     * @param name 名称
     * @param speed 速度
     * @param napRange 打盹范围 s [2,10] 请限定在2 到5秒以内
     */
    public MyThread(String name, int speed, int napRange) {
        this.name = name;
        this.speed = speed;
        this.napRange = napRange;
    }

    @Override
    public void run() {
        //当前距离
        int currentDistance = 0;
        //总用时
        int time = 0;
        while (currentDistance < DISTANCE) {
            if (finished) {
                System.out.println("---->比赛已经结束了，【" + name + "】 前进到" + currentDistance + "米");
                //有达到终点则结束比赛
                return;
            }
            sleep(1);
            time++;
            currentDistance += speed;
            System.out.println("【" + name + "】 前进了" + currentDistance + "米, 已用时：" + time + "秒");
            //判断是否会打盹，是的话则进行打盹
            if (willNap(napRange)) {
                int napTime = randomNapTime(napRange);
                time += napTime;
                sleep(napTime);
                System.out.println("【" + name + "】打盹了" + napTime + "秒!");
            }
        }
        System.out.println("【" + name + "】 赢得了比赛~~ 共用时" + time + "秒~~");
        finished = true;


    }

    /**
     * 是否会打盹
     */
    public static boolean willNap(int bound) {
        return ThreadLocalRandom.current().nextInt(bound * 1000) > 1500;
    }

    /**
     * 获取打盹时间
     * @param bound 打盹最长时间
     * @return 打盹时间
     */
    private static int randomNapTime(int bound) {
        ThreadLocalRandom threadLocalRandom = ThreadLocalRandom.current();
        return threadLocalRandom.nextInt(1, bound);
    }

    /**
     * 休眠
     * @param seconds 休眠时间
     */
    private static void sleep(int seconds) {
        try {
            TimeUnit.SECONDS.sleep(seconds);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    /* *************************测试****************************************** */

    public static void main(String[] args) throws InterruptedException {
        System.out.println("******************百米赛跑开始啦！******************");
        MyThread rabbit = new MyThread("--兔子--", 20, 5);
        MyThread tortoise = new MyThread("==乌龟==", 10, 2);
        rabbit.start();
        tortoise.start();

        tortoise.join();
        rabbit.join();
        System.out.println("******************百米赛跑结束啦！******************");
    }
}
